// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
#include "pch.h"
#include "Forecast.h"
#include "ForecastGroup.h"

using namespace Weathr;

using namespace Platform;
using namespace std;
using namespace utility;
using namespace Windows::Foundation;
using namespace Windows::UI::Xaml::Media::Animation;

uint32 NextUid = 0; // Forecast objects always created from the ASTA, so no need to make this thread-safe.

Forecast::Forecast(const LatLon& location)
    : m_latlon(location)
    , m_pending(true)
    , m_uid(NextUid++)
    , m_screenLocationTop(0)
    , m_screenLocationLeft(0)
    , m_visible(false)
    , m_selected(false)
    , m_homeForecast(false)
    , m_updateFailed(false)
{
    LastCheckin = datetime();
    XMStoreFloat4(&m_sphereCoordinates, m_latlon.ToSphereCoordinates(1.0f));
}

WeatherData^ Forecast::GetForDate(DateTime date) const
{
    auto it = find_if(begin(m_data), end(m_data), [&date](WeatherData^ data)
    {
        return date.UniversalTime == data->Date.UniversalTime;
    });
    return it != end(m_data) ? *it : nullptr;
}

void Forecast::UpdateWeatherData(const vector<WeatherData^>& weatherData)
{
    for (auto data : weatherData)
    {
        data->IsToday = false;

        const auto date = data->Date;
        auto it = find_if(begin(m_data), end(m_data), [date](WeatherData^ data)
        {
            return data->Date.UniversalTime == date.UniversalTime;
        });
        // Add to collection if new.
        if (it == end(m_data))
        {
            m_data.emplace_back(data);
        }
        // Otherwise, update with new weather data.
        else
        {
            bool current = *it == Current;
            *it = data;
            if (current)
            {
                Current = data;
            }
        }
    }

    // If an object was not touched, we assume it points to expired data (for example, weather data from yesterday.)
    for (auto it = begin(m_data); it != end(m_data); ++it)
    {
        if (find_if(begin(weatherData), end(weatherData), [it](WeatherData^ data)
        {
            return data->Date.UniversalTime == (*it)->Date.UniversalTime;
        }) == end(weatherData))
        {
            it = m_data.erase(it);
        }
    }

    // Update earliest and latest members.
    auto minmax = minmax_element(begin(m_data), end(m_data), [](WeatherData^ data1, WeatherData^ data2)
    {
        return data1->Date.UniversalTime < data2->Date.UniversalTime;
    });
    MinDate = (*minmax.first)->Date;
    MaxDate = (*minmax.second)->Date;
    (*minmax.first)->IsToday = true;
}
